home *** CD-ROM | disk | FTP | other *** search
Text File | 1990-03-10 | 26.2 KB | 1,176 lines |
- Newsgroups: comp.sources.misc
- subject: v11i024: another menu prog
- From: mike@milhow2.UUCP (Mike Howard)
- Sender: allbery@uunet.UU.NET (Brandon S. Allbery - comp.sources.misc)
-
- Posting-number: Volume 11, Issue 24
- Submitted-by: mike@milhow2.UUCP (Mike Howard)
- Archive-name: menu_mh/part01
-
- dumb_menu - executes a simple minded menu
-
- Theory of operation: The program reads and parses a menu
- definition file and then loops until the user quits. Menus
- are not pretty - simply numbered options with Q for quit to
- exit.
-
- The menu definition file consists of a title statement
- followed by zero or more options followed by one or item
- definitions.
-
-
- title { this is a Title }
-
- bold clear always-show
-
- item { this is a prompt } { echo "$FOO $BAR" }
- parm "FOO" { prompt for FOO }
- parm "BAR" { prompt for BAR }
- ;
-
- Mike Howard
- how@milhow1.uunet.uu.net
-
- ---------------------cut here --------------------------------
- #! /bin/sh
- # This is a shell archive. Remove anything before this line, then unpack
- # it by saving it into a file and typing "sh file". To overwrite existing
- # files, type "sh file -c". You can also feed this as standard input via
- # unshar, or by typing "sh <file", e.g.. If this archive is complete, you
- # will see the following message at the end:
- # "End of archive 1 (of 1)."
- # Contents: MANIFEST Makefile README directory dumb_menu.1 dumb_menu.l
- # dumb_menu.y menu.def sub.menu
- # Wrapped by mike@milhow2 on Thu Mar 8 16:00:36 1990
- PATH=/bin:/usr/bin:/usr/ucb ; export PATH
- if test -f 'MANIFEST' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'MANIFEST'\"
- else
- echo shar: Extracting \"'MANIFEST'\" \(393 characters\)
- sed "s/^X//" >'MANIFEST' <<'END_OF_FILE'
- X File Name Archive # Description
- X-----------------------------------------------------------
- X MANIFEST 1 This shipping list
- X Makefile 1
- X README 1
- X directory 1
- X dumb_menu.1 1
- X dumb_menu.l 1
- X dumb_menu.y 1
- X menu.def 1
- X sub.menu 1
- END_OF_FILE
- if test 393 -ne `wc -c <'MANIFEST'`; then
- echo shar: \"'MANIFEST'\" unpacked with wrong size!
- fi
- # end of 'MANIFEST'
- fi
- if test -f 'Makefile' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'Makefile'\"
- else
- echo shar: Extracting \"'Makefile'\" \(939 characters\)
- sed "s/^X//" >'Makefile' <<'END_OF_FILE'
- X# CFLAGS = -g -DFLEX_DEBUG
- X# CFLAGS = -g
- X# CFLAGS = -g -DYYDEBUG
- XCFLAGS = -O -DTERMIO -DTERMCAP
- XLDFLAGS = -ly -ltermcap
- X
- X# C source files
- X# Yacc source files
- XYSRC = dumb_menu.y
- XYCCC = $(YSRC:.y=.c)
- XYOBJ = $(YSRC:.y=.o)
- X
- XLSRC = dumb_menu.l
- XLEX = flex
- XLFLAGS =
- X
- Xdumb_menu : $(YCCC) lex.yy.c
- X $(CC) $(CFLAGS) $(YCCC) $(LDFLAGS) -o dumb_menu
- X
- Xdumb_menu.0s : dumb_menu.c lex.yy.c
- X $(CC) $(CFLAGS) -M0s dumb_menu.c $(LDFLAGS) -o dumb_menu.0s
- X
- Xlex.yy.c : dumb_menu.l
- X $(LEX) $(LFLAGS) dumb_menu.l
- X
- Xprt : $(YSRC) $(LSRC)
- X for x in $? ; do \
- X pr -f -l60 -e8 -o2 $$x | lp -dlaser ;\
- X done
- X touch prt
- X
- Xtar :
- X format /dev/rfd096ds9
- X tar cvf /dev/fd096ds9 $(YSRC) $(LSRC) *.1 Makefile s.* *.doc menu.def \
- X *.menu dumb_menu dumb_menu.0s
- X
- Xclean :
- X rm -f $(OBJS) $(YCCC) lex.yy.c
- X
- Xkit : $(YSRC) $(LSRC) dumb_menu.1 Makefile menu.def sub.menu directory
- X makekit -m $(YSRC) $(LSRC) dumb_menu.1 Makefile menu.def sub.menu \
- X directory README
- X touch kit
- END_OF_FILE
- if test 939 -ne `wc -c <'Makefile'`; then
- echo shar: \"'Makefile'\" unpacked with wrong size!
- fi
- # end of 'Makefile'
- fi
- if test -f 'README' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'README'\"
- else
- echo shar: Extracting \"'README'\" \(610 characters\)
- sed "s/^X//" >'README' <<'END_OF_FILE'
- X dumb_menu - executes a simple minded menu
- X
- X Theory of operation: The program reads and parses a menu
- X definition file and then loops until the user quits. Menus
- X are not pretty - simply numbered options with Q for quit to
- X exit.
- X
- X The menu definition file consists of a title statement
- X followed by zero or more options followed by one or item
- X definitions.
- X
- X
- X title { this is a Title }
- X
- X bold clear always-show
- X
- X item { this is a prompt } { echo "$FOO $BAR" }
- X parm "FOO" { prompt for FOO }
- X parm "BAR" { prompt for BAR }
- X ;
- X
- XMike Howard
- Xhow@milhow1.uunet.uu.net
- END_OF_FILE
- if test 610 -ne `wc -c <'README'`; then
- echo shar: \"'README'\" unpacked with wrong size!
- fi
- # end of 'README'
- fi
- if test -f 'directory' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'directory'\"
- else
- echo shar: Extracting \"'directory'\" \(99 characters\)
- sed "s/^X//" >'directory' <<'END_OF_FILE'
- Xdumb_menu.1:The Manual Page
- Xdumb_menu.l:The Lexical Analyzer
- Xdumb_menu.y:The parser & Main Program
- END_OF_FILE
- if test 99 -ne `wc -c <'directory'`; then
- echo shar: \"'directory'\" unpacked with wrong size!
- fi
- # end of 'directory'
- fi
- if test -f 'dumb_menu.1' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'dumb_menu.1'\"
- else
- echo shar: Extracting \"'dumb_menu.1'\" \(3436 characters\)
- sed "s/^X//" >'dumb_menu.1' <<'END_OF_FILE'
- X. \" -*- nroff -*-
- X. \" @(#)dumb_menu.1 1.2 90/03/08
- X.DA March 8, 1990
- X.TH DUMB_MENU 1 "local"
- X.SH NAME
- Xdumb_menu \- executes a simple minded menu
- X.SH SYNOPSIS
- X.B dumb_menu
- X[ -h | options ]
- X.SH DESCRIPTION
- X.PP
- X.B -m path
- Xsets the path to the menu definition file. Default is
- X.I ./menu.def.
- X.PP
- X.B -s path
- Xsets path for the shell which will execute the selected menu command.
- XDefault is
- X.I /bin/sh
- X.PP
- X.B -c path
- Xsets the path to
- X.B cat
- Xwhich is used to display the command selected in debug mode.
- X.PP
- X.B -D
- Xincrements debug mode. There are two modes - one simply lists the
- Xfile and cat's the selected options rather than executing them.
- XThe other displays the statements which are discovered during the
- Xparsing phase.
- X.B -v
- Ximplements a quasi-verbose mode. This is done by prepending the
- Xcommand
- X.I set -x
- Xto the front of the shell script prior to feeding it to a shell.
- X.PP
- XTheory of operation: The program reads and parses a menu definition
- Xfile and then loops until the user quits. Menus are not pretty -
- Xsimply numbered options with Q for quit to exit.
- X.PP
- XThe menu definition file consists of a
- X.B title
- Xstatement followed by zero or more
- X.B options
- Xfollowed by one or
- X.B item
- Xdefinitions.
- X.PP
- XThe
- X.B title
- Xstatement contains the menu title enclosed in braces ({ foo }).
- X.IP
- Xtitle { some text }
- X.PP
- XTitles the menu with the title ``some text''.
- X.PP
- XLegal menu options are
- X.B clear, bold,
- Xand
- X.B always-show.
- X.HP
- X.B clear
- Xcauses the screen to be cleared prior to displaying the menu. It also
- Xcauses a
- X.I [ Hit Return to Continue ]
- Xmessage to be displayed upon the completion of processing a selection.
- X.HP
- X.B bold
- Xcauses the menu title to be displayed in
- X.I standout mode,
- Xif the terminal type is defined and supports it.
- X.HP
- X.B always-show
- Xcauses the menu selections to always be re-displayed after a menu
- Xselection is completed. Otherwise, only the title and the ``Q) to
- XQuit, ? for menu'' message is displayed.
- X.PP
- XItem definitions begin with the key word
- X.B item
- Xand are terminated by a semi-colon (;).
- XThe word
- X.B item
- Xis followed by the prompt string enclosed in braces, which is
- Xfollowed by the shell script to run, enclosed in braces.
- XThe shell script is followed by zero or more parameter definitions.
- X.PP
- XParameter definitions begin with the key word
- X.B parm,
- Xare followed by the parameter identifier enclosed in double
- Xquote marks ("), which is
- Xfollowed by the prompt for the parameter enclosed in braces.
- XParameter identifiers may only contain alphanumeric
- Xcharacters (A-Z,a-z, 0-9, and _), as a crude form of error checking.
- X.PP
- X.B NOTE:
- Xtext bounded by braces (\ {\ }\ ) in
- X.B title, item,
- Xand
- X.B parm
- Xstatements may contain any character except nulls ('\\0') and
- Xnon-escaped back-slashes (\\) and right braces (}). Nulls are
- Xillegal, because the lexical analyzer won't deal with them.
- XSingle back-slashes and right braces are written as \\\\ and \\},
- Xrespectively. Other back-slash escape sequences needed in scripts for
- Xother reasons do not need to be escaped \- i.e. echo "\\nfoo" in a
- Xshell script does
- X.I not
- Xneed to be written echo "\\\\nfoo".
- X.IP
- Xtitle { this is a Title }
- X.IP
- Xbold clear always-show
- X.IP
- Xitem { this is a prompt } { echo "$FOO $BAR" }
- X.IP
- Xparm "FOO" { prompt for FOO }
- X.IP
- Xparm "BAR" { prompt for BAR }
- X.IP
- X;
- X.SH DIAGNOSTICS
- X.PP
- XThe diagnostics during the parse of the menu definition are all but
- Xnon-existent.
- X.SH BUGS
- X.PP
- XHas no provision for menus which exceed one screen in size.
- END_OF_FILE
- if test 3436 -ne `wc -c <'dumb_menu.1'`; then
- echo shar: \"'dumb_menu.1'\" unpacked with wrong size!
- fi
- # end of 'dumb_menu.1'
- fi
- if test -f 'dumb_menu.l' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'dumb_menu.l'\"
- else
- echo shar: Extracting \"'dumb_menu.l'\" \(2584 characters\)
- sed "s/^X//" >'dumb_menu.l' <<'END_OF_FILE'
- X /* @(#)dumb_menu.l 1.2 90/03/08 */
- X /* copyrite (c) Miller/Howard Investments, 1990 */
- X
- X%{
- X/* this thing is designed to use flex, not lex. If you don't have
- X it, then you'll have to re-write the lexical analyser */
- X
- X#include <ctype.h>
- X
- X char *saved_text;
- X%}
- X
- X /* global definitions */
- X
- X%x P_STATE T_STATE
- X
- X%%
- X
- Xitem return ITEM;
- Xparm return PARM;
- Xtitle return TITLE;
- Xclear return CLEAR;
- Xbold return BOLD;
- X"always-show" return ALWAYS_SHOW;
- X"{" { BEGIN T_STATE ; }
- X\" { BEGIN P_STATE; }
- X";" return ';';
- X[ \t]+ ;
- X\n line_number++;
- X. return ERROR;
- X
- X<T_STATE>"\\}" add_text("}");
- X<T_STATE>"}" {
- X strip_white_space();
- X yylval.txt = saved_text;
- X saved_text = (char *)0;
- X BEGIN 0;
- X return TEXT; }
- X<T_STATE>"\\\n" {
- X line_number++;
- X add_text(yytext);
- X }
- X<T_STATE>\\. add_text(yytext);
- X<T_STATE>[^\\}\n]+ add_text(yytext);
- X<T_STATE>"\n" {
- X line_number++;
- X add_text("\n");
- X }
- X
- X<P_STATE>[A-Za-z0-9_]+ add_text(yytext);
- X<P_STATE>\" {
- X if (saved_text) {
- X strip_white_space();
- X yylval.txt = saved_text;
- X saved_text = (char *)0;
- X BEGIN 0;
- X return PARM_NAME;
- X }
- X fprintf(stderr, "lex error\n");
- X lex_errors++;
- X return ERROR;
- X }
- X%%
- X
- X/* c program text */
- X
- X#define INIT_SIZE 256
- X#define INC_SIZE 64
- X
- Xadd_text(s)
- Xchar *s;
- X{
- X static int saved_length;
- X static int room_left;
- X int len = strlen(s);
- X static int saved_size;
- X
- X if (!saved_text) {
- X memset(saved_text = malloc(INIT_SIZE), '\0', INIT_SIZE);
- X room_left = INIT_SIZE;
- X saved_size = INIT_SIZE;
- X saved_length = 0;
- X }
- X
- X len++; /* inc len to account for terminating null */
- X while (len >= room_left) {
- X saved_text = realloc(saved_text, saved_size += INC_SIZE);
- X room_left += INC_SIZE;
- X }
- X
- X memcpy(saved_text + saved_length, s, len);
- X /* the trailing null will be overwritten next time
- X so it doesn't count in computing room left */
- X room_left -= --len;
- X saved_length += len;
- X}
- X
- Xstrip_white_space()
- X{
- X char *cp;
- X char *sp;
- X
- X if (!saved_text)
- X return;
- X
- X for (cp = saved_text + strlen(saved_text) - 1;cp > saved_text;cp--) {
- X if (!isspace(*cp))
- X break;
- X }
- X *++cp = '\0';
- X
- X for (cp=saved_text;*cp && isspace(*cp);cp++)
- X ;
- X
- X /* is it all white? */
- X if (!*cp && cp > saved_text) {
- X saved_text = realloc(saved_text, 1);
- X *saved_text = '\0';
- X return;
- X }
- X
- X /* is there any leading white space? */
- X if (cp > saved_text) {
- X char *tmp;
- X int len;
- X
- X tmp = malloc(len = strlen(cp) + 1);
- X memcpy(tmp, cp, len);
- X free(saved_text);
- X saved_text = tmp;
- X
- X return;
- X }
- X
- X saved_text = realloc(saved_text, strlen(saved_text) + 1);
- X}
- X
- X#ifdef yywrap
- X#undef yywrap
- X#endif
- END_OF_FILE
- if test 2584 -ne `wc -c <'dumb_menu.l'`; then
- echo shar: \"'dumb_menu.l'\" unpacked with wrong size!
- fi
- # end of 'dumb_menu.l'
- fi
- if test -f 'dumb_menu.y' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'dumb_menu.y'\"
- else
- echo shar: Extracting \"'dumb_menu.y'\" \(11883 characters\)
- sed "s/^X//" >'dumb_menu.y' <<'END_OF_FILE'
- X%{
- X/* @(#)dumb_menu.y 1.3 90/03/08 */
- X
- Xstatic char *cpy_str =
- X "Copyright (c), Mike Howard, 1990, all rights reserved";
- X
- X/* Conditions of use:
- X
- X This software is not for sale and is not to be sold by or
- X to anyone.
- X
- X You may use this software and may distribute it to anyone
- X you wish to provided you distribute the entire distribution
- X package w/o any deletions (i.e. include all the source code).
- X
- X I do not warrent this software to do anything at all and
- X am not responsible for anything which happens as a result of
- X its use.
- X*/
- X
- X#include <stdio.h>
- X#include <fcntl.h>
- X#include <string.h>
- X#include <signal.h>
- X#include <setjmp.h>
- X
- Xstruct parm {
- X struct parm *next;
- X char *prompt;
- X char *identifier;
- X char *value;
- X};
- X
- Xstruct item {
- X struct item *next;
- X char *prompt;
- X char *command;
- X struct parm *parms;
- X};
- X
- Xstruct item *menu_head;
- Xstruct item *menu_tail;
- X
- Xint max_item;
- X
- Xstruct parm *parm_list;
- X
- Xchar *menu_title;
- X
- Xchar *malloc();
- Xchar *realloc();
- X
- Xint lex_errors;
- Xint yacc_errors;
- Xint line_number;
- X
- X/* flags */
- Xint clear_flag;
- Xint bold_flag;
- Xint always_display_menu_flag;
- X
- X/* Menus begin with a title definition
- X title { text for the title }
- X
- X This is followed by one or more menu-item definitions of the form:
- X
- X item { prompt } { shell command }
- X parm "name" { prompt }
- X parm "name" { prompt }
- X ;
- X
- X the crud in between braces may contain any character, including
- X escapped braces and back-slash (\).
- X The crud in between the double quotes may ONLY contain letters, digits,
- X and underscores;
- X
- X Sub-menus are formed by running dumb_menu as the shell process, pointed
- X to an appropriate sub-menu definition file.
- X
- X There is no provision for menus which require more than one screen
- X to display.
- X*/
- X
- X#define DEBUG0(fmt) if(debug_mode>1)printf(fmt);
- X#define DEBUG1(fmt,aa) if(debug_mode>1)printf(fmt,aa);
- X#define DEBUG2(fmt,aa,bb) if(debug_mode>1)printf(fmt,aa,bb);
- X#define DEBUG3(fmt,aa,bb,cc) if(debug_mode>1)printf(fmt,aa,bb,cc);
- X
- X%}
- X
- X%union {
- X int ival;
- X char *txt;
- X char chr;
- X double dbl;
- X struct item *itm;
- X struct parm *prm;
- X}
- X
- X%token <ival> NUMBER
- X%token <dbl> FLOAT
- X%token <txt> TEXT PARM_NAME
- X%token PARM ITEM TITLE ERROR
- X%token CLEAR BOLD ALWAYS_SHOW
- X
- X%type <itm> menu item
- X%type <prm> parm
- X
- X%%
- X
- Xmenu : title menu_flags item
- X {
- X menu_head =
- X menu_tail = $3;
- X DEBUG1("Initial Menu Item:\n %s\n", $3->prompt);
- X }
- X | menu item
- X {
- X menu_tail->next = $2;
- X menu_tail = $2;
- X DEBUG1("Additional Menu Item:\n %s\n", $2->prompt);
- X }
- X ;
- X
- Xtitle : TITLE TEXT
- X {
- X menu_title = $2;
- X DEBUG1("menu title '%s'\n", $2);
- X }
- X ;
- X
- Xmenu_flags :
- X | menu_flags menu_flag
- X ;
- X
- Xmenu_flag : CLEAR
- X {
- X clear_flag++;
- X }
- X | BOLD
- X {
- X bold_flag++;
- X }
- X | ALWAYS_SHOW
- X {
- X always_display_menu_flag++;
- X }
- X ;
- X
- Xitem : ITEM TEXT TEXT parms ';'
- X {
- X $$ = make_new_item($2, $3, parm_list);
- X parm_list = (struct parm *)0;
- X }
- X ;
- X
- Xparms : /* empty */
- X | parms parm
- X ;
- X
- Xparm : PARM PARM_NAME TEXT
- X {
- X $$ = make_new_parm($2, $3);
- X $$->next = parm_list;
- X parm_list = $$;
- X DEBUG2("parm: %s\n'%s'\n", $2, $3);
- X }
- X ;
- X
- X%%
- X
- Xchar *use_msg = "usage: %s [-h | option(s) ]\n";
- X
- Xextern char *optarg;
- Xextern int optind, opterr;
- Xint tty_in;
- XFILE *tty_file;
- Xint argcc;
- Xchar **argvv;
- Xchar *progname;
- Xchar *in_fname = "stdin";
- Xchar *menu_fname = "./menu.def";
- Xchar *shell_path = "/bin/sh";
- Xchar *cat_path = "/bin/cat";
- Xchar *cmd_path;
- Xchar *cmd_name;
- X
- Xstruct item *selected_item;
- Xstruct parm *selected_parms;
- XFILE *tmp_file;
- Xchar *tmp_fname;
- X
- Xint verbose;
- Xint debug_mode;
- X
- Xchar *hlp[] = {
- X"Option Function",
- X"-m file set menu-definition file name to 'file' (menu.def)",
- X"-s path path to shell to execute scripts",
- X"-c path path to 'cat' for simple debug mode",
- X"-v make command execution verbose (via set -xv)",
- X"-D increment debug mode",
- X(char *)0};
- X
- Xint display_menu_flag = 1;
- Xjmp_buf env;
- X#define SIGS_FOR_JMP 1
- X#define SIGS_FOR_CHILD 2
- X
- Xmain(argc, argv)
- Xint argc;
- Xchar **argv;
- X{
- X int item_idx;
- X
- X init(argc, argv);
- X
- X if (yyparse())
- X fatal("Parse Error");
- X
- X if (lex_errors || yacc_errors)
- X fatal("corrupt menu definition");
- X
- X if (debug_mode) {
- X item_idx = 1;
- X for (selected_item=menu_head;selected_item;
- X selected_item = selected_item->next) {
- X printf("%2d. %s\n", item_idx++, selected_item->prompt);
- X printf("%s\n", selected_item->command);
- X for (selected_parms=selected_item->parms;selected_parms;
- X selected_parms = selected_parms->next)
- X printf("%s: '%s'\n", selected_parms->prompt,
- X selected_parms->identifier);
- X }
- X }
- X
- X init_terminal();
- X
- X do_menu();
- X}
- X
- Xinit(argc, argv)
- Xint argc;
- Xchar **argv;
- X{
- X int i;
- X int c;
- X extern char *optarg;
- X extern int optind, opterr;
- X
- X while ((c = getopt(argc, argv, "hcsm:vD")) != EOF) {
- X switch (c) {
- X case 'h':
- X for (i=0;hlp[i];i++)
- X printf("%s\n", hlp[i]);
- X fatal((char *)0);
- X case 's':
- X shell_path = optarg;
- X break;
- X case 'c':
- X cat_path = optarg;
- X break;
- X case 'm':
- X menu_fname = optarg;
- X break;
- X case 'v':
- X verbose++;
- X break;
- X case 'D':
- X debug_mode++;
- X break;
- X case '?':
- X fatal((char *)0);
- X }
- X }
- X
- X argcc = argc;
- X argvv = argv;
- X progname = argv[0];
- X if (strcmp(menu_fname, "-")) {
- X close(0);
- X
- X if (open(menu_fname, O_RDONLY) < 0) {
- X char buf[80];
- X
- X sprintf(buf, "cannot open menu definition: %s", menu_fname);
- X fatal(buf);
- X }
- X }
- X
- X if ((tty_in = open("/dev/tty", O_RDONLY)) < 0)
- X fatal("cannot open tty - must be run interactively");
- X tty_file = fdopen(tty_in, "r");
- X
- X cmd_path = debug_mode ? cat_path : shell_path;
- X if (cmd_name = strrchr(cmd_path, '/'))
- X cmd_name++;
- X else
- X cmd_name = cmd_path;
- X}
- X
- Xstruct parm *make_new_parm(identifier, prompt)
- Xchar *identifier;
- Xchar *prompt;
- X{
- X struct parm *parm_ptr = (struct parm *)malloc(sizeof(struct parm));
- X
- X if (!parm_ptr)
- X fatal("malloc() error");
- X
- X parm_ptr->next = (struct parm *)0;
- X parm_ptr->prompt = prompt;
- X parm_ptr->identifier = identifier;
- X parm_ptr->value = "";
- X
- X return parm_ptr;
- X}
- X
- Xstruct item *make_new_item(prompt, command, parms)
- Xchar *prompt;
- Xchar *command;
- Xstruct parm *parms;
- X{
- X struct item *item_ptr = (struct item *)malloc(sizeof(struct item));
- X
- X if (!item_ptr)
- X fatal("malloc() error");
- X
- X item_ptr->next = (struct item *)0;
- X item_ptr->prompt = prompt;
- X item_ptr->command = command;
- X item_ptr->parms = parms;
- X
- X return item_ptr;
- X}
- X
- Xchar tty_bp[1024];
- Xchar tty_caps[1024];
- Xchar *term_cm;
- Xchar *term_so;
- Xchar *term_se;
- Xint term_sg;
- Xchar *term_cl;
- Xint term_lines;
- Xchar PC;
- Xchar *BC;
- Xchar *UP;
- Xshort ospeed;
- X
- Xint outc(c)
- Xint c;
- X{
- X putc(c, stdout);
- X}
- X
- Xinit_terminal()
- X{
- X char *getenv();
- X char *tty_type = getenv("TERM");
- X char *cp = tty_caps;
- X char *tgetstr();
- X
- X if (!tty_type || tgetent(tty_bp, tty_type) <= 0) {
- X clear_flag =
- X bold_flag = 0;
- X return;
- X }
- X
- X PC = *tgetstr("pc", &cp);
- X BC = tgetstr("bc", &cp);
- X UP = tgetstr("up", &cp);
- X#ifdef TERMIO
- X {
- X#include <sys/termio.h>
- X
- X struct termio termio;
- X
- X ioctl(0, TCGETA, &termio);
- X ospeed = termio.c_cflag & CBAUD;
- X }
- X#undef ECHO /* conflicts with lex code */
- X#endif /* TERMIO */
- X term_cm = tgetstr("cm", &cp);
- X if (bold_flag) {
- X term_so = tgetstr("so", &cp);
- X term_se = tgetstr("se", &cp);
- X term_sg = tgetnum("sg");
- X if (!term_so)
- X bold_flag = 0;
- X }
- X if (clear_flag) {
- X term_cl = tgetstr("cl", &cp);
- X term_lines = tgetnum("li");
- X if (!term_cl)
- X clear_flag = 0;
- X }
- X}
- X
- Xdo_menu()
- X{
- X int item_idx;
- X int pid;
- X
- X while (1) {
- X again:
- X setjmp(env);
- X set_signals(SIGS_FOR_JMP);
- X
- X while (1) {
- X char buf[80];
- X char *cp;
- X int rsp;
- X
- X display_menu();
- X fgets(buf, 80, tty_file);
- X if (cp = strchr(buf, '\n'))
- X *cp = '\0';
- X
- X if (strchr(buf, 'Q') || strchr(buf, 'q'))
- X exit(0);
- X
- X if (strchr(buf, '?')) {
- X display_menu_flag = 1;
- X goto again;
- X }
- X
- X if (sscanf(buf, "%d", &item_idx) != 1) {
- X printf("'%s' is not a legal response\n", buf);
- X goto again;
- X }
- X
- X if (--item_idx < 0 || item_idx >= max_item) {
- X printf("'%s' is not a legal response\n", buf);
- X goto again;
- X }
- X else
- X break;
- X }
- X
- X selected_item = menu_head;
- X while (item_idx-- > 0)
- X selected_item = selected_item->next;
- X
- X selected_parms = selected_item->parms;
- X
- X while (selected_parms) {
- X char buf[256];
- X char *cp;
- X
- X printf("%s: ", selected_parms->prompt);
- X fflush(stdout);
- X fgets(buf, 255, tty_file);
- X if (cp = strchr(buf, '\n'))
- X *cp = '\0';
- X
- X strcpy(selected_parms->value = malloc(strlen(buf) + 1), buf);
- X selected_parms = selected_parms->next;
- X }
- X
- X tmp_fname = tmpnam((char *)0);
- X set_signals(SIGS_FOR_CHILD);
- X if ((tmp_file = fopen(tmp_fname, "w")) == NULL)
- X fatal("cannot create temp file for shell");
- X if (verbose)
- X fprintf(tmp_file, "set -xv\n");
- X for (selected_parms=selected_item->parms;selected_parms;
- X selected_parms=selected_parms->next) {
- X fprintf(tmp_file, "%s=\"%s\"\n", selected_parms->identifier,
- X selected_parms->value);
- X free(selected_parms->value);
- X selected_parms->value = "";
- X }
- X fprintf(tmp_file, "%s\n", selected_item->command);
- X fclose(tmp_file);
- X
- X if ( !(pid = fork()) ) {
- X /* reset signals so that DEL,... work correctly */
- X reset_signals();
- X close(0);
- X dup(tty_in);
- X close(tty_in);
- X fclose(tty_file);
- X execl(cmd_path, cmd_name, tmp_fname, (char *)0);
- X fatal("exec of command failed");
- X }
- X
- X wait_for_child(pid);
- X unlink(tmp_fname);
- X tmp_fname = (char *)0;
- X if (clear_flag) {
- X char buf[80];
- X
- X printf("[Press Return to Continue]");
- X fflush(stdout);
- X fgets(buf, 80, tty_file);
- X }
- X }
- X reset_signals();
- X}
- X
- Xdisplay_menu()
- X{
- X struct item *ptr = menu_head;
- X int i;
- X
- X /* if we clear the screen, then do it, otherwise skip a line */
- X if (clear_flag)
- X tputs(term_cl, term_lines, outc);
- X else
- X putc('\n', stdout);
- X
- X /* this is not correct for magic cookie tubes - but I don't feel
- X like counting lines in menu_title, maintaining line counts in the
- X case we don't clear-screen-before-displaying, ...
- X So if you have a stupid tube - it is going to flash */
- X if (bold_flag) {
- X tputs(term_so, 1, outc);
- X printf("%s", menu_title);
- X tputs(term_se, 1, outc);
- X putc('\n', stdout);
- X }
- X else
- X printf("%s\n", menu_title);
- X
- X if (display_menu_flag) {
- X for (i=0;ptr;i++,ptr = ptr->next)
- X printf("%2d. %s\n", i + 1, ptr->prompt);
- X max_item = i;
- X }
- X
- X printf( always_display_menu_flag ? "Q) to End - choice? " :
- X "Q) to End, ?) for Menu - choice? ");
- X fflush(stdout);
- X
- X display_menu_flag = always_display_menu_flag;
- X}
- X
- X#include "lex.yy.c"
- X
- X
- Xfatal(s)
- Xchar *s;
- X{
- X extern int errno;
- X char msg_buf[80];
- X
- X fprintf(stderr, use_msg, progname);
- X if (s)
- X fprintf(stderr, "%s\n", s);
- X
- X if (errno) {
- X sprintf(msg_buf, "fatal error '%s': line %d", menu_fname, line_number);
- X perror(msg_buf);
- X }
- X exit(1);
- X}
- X
- Xvoid trapoid(sig)
- Xint sig;
- X{
- X if (tmp_fname)
- X unlink(tmp_fname);
- X
- X exit(sig);
- X}
- X
- Xdo_longjmp(sig)
- Xint sig;
- X{
- X longjmp(env, 0);
- X}
- X
- Xwait_for_child(pid)
- Xint pid;
- X{
- X int wait_ret;
- X int status;
- X extern int errno;
- X
- X while ((wait_ret = wait(&status)) != pid) {
- X /* test to see if child is still there - if not, then return */
- X if (kill(pid, 0) < 0)
- X return;
- X }
- X}
- X
- Xset_signals(flag)
- Xint flag;
- X{
- X switch (flag) {
- X case SIGS_FOR_JMP:
- X signal(SIGHUP, trapoid);
- X signal(SIGINT, do_longjmp);
- X signal(SIGQUIT, do_longjmp);
- X signal(SIGTERM, trapoid);
- X break;
- X case SIGS_FOR_CHILD:
- X signal(SIGHUP, trapoid);
- X signal(SIGINT, SIG_IGN);
- X signal(SIGQUIT, SIG_IGN);
- X signal(SIGTERM, trapoid);
- X break;
- X }
- X}
- X
- Xreset_signals()
- X{
- X signal(SIGHUP, SIG_DFL);
- X signal(SIGINT, SIG_DFL);
- X signal(SIGQUIT, SIG_DFL);
- X signal(SIGTERM, SIG_DFL);
- X signal(SIGCLD, SIG_DFL);
- X}
- END_OF_FILE
- if test 11883 -ne `wc -c <'dumb_menu.y'`; then
- echo shar: \"'dumb_menu.y'\" unpacked with wrong size!
- fi
- # end of 'dumb_menu.y'
- fi
- if test -f 'menu.def' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'menu.def'\"
- else
- echo shar: Extracting \"'menu.def'\" \(576 characters\)
- sed "s/^X//" >'menu.def' <<'END_OF_FILE'
- Xtitle { Test Menu }
- X
- Xclear bold always-show
- X
- Xitem { First Item }
- X{ echo $PARM1 }
- Xparm "PARM1" { Input Parm 1 }
- X;
- X
- Xitem { Second Item }
- X{ echo "This is $PARM and $FOO" }
- Xparm "PARM" { input value for PARM }
- Xparm "FOO" {input value for FOO }
- X;
- X
- Xitem { Submenu }
- X{ awk -F: '
- XBEGIN {
- X print "title { A dynamically constructed submenu \}"
- X print "clear bold"
- X\}
- X{
- X print "item { Browse " $2 " \} { less -cM " $1 " \} ;"
- X\}
- X' directory | dumb_menu -m -
- X}
- X;
- X
- Xitem { Execute a Command }
- X{ $CMD }
- Xparm "CMD" { Command Line }
- X;
- X
- Xitem { Another Submenu }
- X{ dumb_menu -m sub.menu }
- X;
- END_OF_FILE
- if test 576 -ne `wc -c <'menu.def'`; then
- echo shar: \"'menu.def'\" unpacked with wrong size!
- fi
- # end of 'menu.def'
- fi
- if test -f 'sub.menu' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'sub.menu'\"
- else
- echo shar: Extracting \"'sub.menu'\" \(215 characters\)
- sed "s/^X//" >'sub.menu' <<'END_OF_FILE'
- Xtitle { A non-descript submenu
- XWith a multi-line
- Xtitle }
- X
- Xitem { Sub-Item 1
- X long prompt }
- X{ echo "\nSub-Item 1" }
- X;
- X
- Xitem { Sub-Item 2 }
- X{ echo "\nSub-Item 2" }
- X;
- X
- Xitem { Sub-Item 3 }
- X{ echo "\nSub-Item 3" }
- X;
- END_OF_FILE
- if test 215 -ne `wc -c <'sub.menu'`; then
- echo shar: \"'sub.menu'\" unpacked with wrong size!
- fi
- # end of 'sub.menu'
- fi
- echo shar: End of archive 1 \(of 1\).
- cp /dev/null ark1isdone
- MISSING=""
- for I in 1 ; do
- if test ! -f ark${I}isdone ; then
- MISSING="${MISSING} ${I}"
- fi
- done
- if test "${MISSING}" = "" ; then
- echo You have the archive.
- rm -f ark[1-9]isdone
- else
- echo You still need to unpack the following archives:
- echo " " ${MISSING}
- fi
- ## End of shell archive.
- exit 0
-
-
-